home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 1 / Amiga Tools.iso / wb-tools / toolmanager / source / library / execobj.c < prev    next >
C/C++ Source or Header  |  1994-06-06  |  28KB  |  924 lines

  1. /*
  2.  * execobj.c  V2.1
  3.  *
  4.  * TMObject, Type: Exec
  5.  *
  6.  * (c) 1990-1993 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerLib.h"
  10.  
  11. /* extended TMObject structure for TMOBJTYPE_Exec objects */
  12. struct TMObjectExec {
  13.                      struct TMObject    eo_Object;
  14.                      UWORD              eo_Type;
  15.                      UWORD              eo_Flags;
  16.                      char              *eo_Command;
  17.                      char              *eo_CurrentDir;
  18.                      LONG               eo_Delay;
  19.                      char              *eo_HotKey;
  20.                      char              *eo_Output;
  21.                      char              *eo_Path;
  22.                      LONG               eo_Priority;
  23.                      char              *eo_PubScreen;
  24.                      LONG               eo_Stack;
  25.                      CxObj             *eo_CxObj;
  26.                      struct TMHandle   *eo_Handle;
  27.                      void              *eo_LinkData;
  28.                      struct TMLink      eo_Link;
  29.                      struct TMTimerReq  eo_TimerReq;
  30.                     };
  31.  
  32. /* eo_Flags */
  33. #define EO_Arguments (1L<<0)
  34. #define EO_ToFront   (1L<<1)
  35.  
  36. /* Tag to Flag mapping table for PackBoolTags */
  37. static struct TagItem flagmap[]={TMOP_Arguments, EO_Arguments,
  38.                                  TMOP_ToFront,   EO_ToFront,
  39.                                  TAG_DONE};
  40.  
  41. /* Structure for path list */
  42. struct PathList {
  43.                  BPTR NextPath; /* Pointer to next PathList */
  44.                  BPTR PathLock; /* Lock on directory */
  45.                 };
  46.  
  47. /* Create an Exec object */
  48. struct TMObject *CreateTMObjectExec(struct TMHandle *handle, char *name,
  49.                                     struct TagItem *tags)
  50. {
  51.  struct TMObjectExec *tmobj;
  52.  
  53.  /* allocate memory for object */
  54.  if (tmobj=(struct TMObjectExec *)
  55.             AllocateTMObject(sizeof(struct TMObjectExec))) {
  56.   struct TagItem *ti,*tstate;
  57.   BOOL noerror=TRUE;
  58.  
  59.   /* Set object defaults */
  60.   tmobj->eo_Type=TMET_CLI;
  61.   tmobj->eo_Command=DefaultNoName;
  62.   tmobj->eo_CurrentDir=DefaultDirName;
  63.   tmobj->eo_Output=DefaultOutput;
  64.   tmobj->eo_Stack=4096;
  65.   tmobj->eo_Handle=handle;
  66.  
  67.   /* Scan tag list */
  68.   tstate=tags;
  69.   while (noerror && (ti=NextTagItem(&tstate))) {
  70.  
  71.    DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  72.  
  73.    switch (ti->ti_Tag) {
  74.     case TMOP_Command:    {
  75.                            char *s=(char *) ti->ti_Data;
  76.                            if (s) tmobj->eo_Command=s;
  77.                           }
  78.                           break;
  79.     case TMOP_CurrentDir: {
  80.                            char *s=(char *) ti->ti_Data;
  81.                            if (s) tmobj->eo_CurrentDir=s;
  82.                           }
  83.                           break;
  84.     case TMOP_Delay:      tmobj->eo_Delay=ti->ti_Data;
  85.                           break;
  86.     case TMOP_ExecType:   {
  87.                            UWORD type=ti->ti_Data;
  88.  
  89.                            /* Sanity check */
  90.                            if ((type <= TMET_Network) || (type == TMET_Hook))
  91.                             tmobj->eo_Type=type;
  92.                            else
  93.                             noerror=FALSE;
  94.                           }
  95.                           break;
  96.     case TMOP_HotKey:     tmobj->eo_HotKey=(char *) ti->ti_Data;
  97.                           break;
  98.     case TMOP_Output:     {
  99.                            char *s=(char *) ti->ti_Data;
  100.                            if (s) tmobj->eo_Output=s;
  101.                           }
  102.                           break;
  103.     case TMOP_Path:       tmobj->eo_Path=(char *) ti->ti_Data;
  104.                           break;
  105.     case TMOP_Priority:   tmobj->eo_Priority=ti->ti_Data;
  106.                           break;
  107.     case TMOP_PubScreen:  tmobj->eo_PubScreen=(char *) ti->ti_Data;
  108.                           break;
  109.     case TMOP_Stack:      tmobj->eo_Stack=ti->ti_Data;
  110.                           break;
  111.    }
  112.   }
  113.  
  114.   /* No errors? */
  115.   if (noerror) {
  116.    BOOL hotkey=tmobj->eo_HotKey!=NULL;
  117.  
  118.    /* HotKey set? Create Commodities object from HotKey description */
  119.    if  (hotkey && (tmobj->eo_CxObj=HotKey(tmobj->eo_HotKey,BrokerPort,
  120.                                           (ULONG) &tmobj->eo_Link))) {
  121.  
  122.     DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->eo_CxObj);
  123.  
  124.     /* Attach object to broker */
  125.     AttachCxObj(Broker,tmobj->eo_CxObj);
  126.    }
  127.  
  128.    /* No HotKey or no HotKey error? */
  129.    if (!hotkey || (tmobj->eo_CxObj && !CxObjError(Broker))) {
  130.     /* No. Set flags */
  131.     tmobj->eo_Flags=PackBoolTags(EO_Arguments,tags,flagmap);
  132.  
  133.     /* Initialize rest of structure */
  134.     tmobj->eo_Link.tml_Linked=(struct TMObject *) tmobj;
  135.     tmobj->eo_Link.tml_Active=FALSE;
  136.     tmobj->eo_TimerReq.tmtr_Request=*deftimereq;
  137.     tmobj->eo_TimerReq.tmtr_Link=&tmobj->eo_Link;
  138.  
  139.     /* All OK */
  140.     return(tmobj);
  141.    }
  142.  
  143.    /* Free resources */
  144.    if (tmobj->eo_CxObj) SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  145.   }
  146.   FreeMem(tmobj,sizeof(struct TMObjectExec));
  147.  }
  148.  
  149.  /* call failed */
  150.  return(NULL);
  151. }
  152.  
  153. /* Delete an Exec object */
  154. BOOL DeleteTMObjectExec(struct TMObjectExec *tmobj)
  155. {
  156.  DEBUG_PRINTF("Delete/Exec (0x%08lx)\n",tmobj);
  157.  
  158.  /* timer request active? */
  159.  if (tmobj->eo_Link.tml_Active) {
  160.   struct IORequest *tr=(struct IORequest *) &tmobj->eo_TimerReq;
  161.  
  162.   /* If timer request still active, abort it */
  163.   if (!CheckIO(tr)) AbortIO(tr);
  164.  
  165.   /* Remove timer request */
  166.   WaitIO(tr);
  167.   tmobj->eo_Link.tml_Active=FALSE;
  168.  }
  169.  
  170.  /* Free internal data */
  171.  if (tmobj->eo_LinkData)
  172.   switch(tmobj->eo_Type) {
  173.    case TMET_HotKey: FreeMem(tmobj->eo_LinkData,sizeof(struct InputEvent));
  174.                      break;
  175.    case TMET_Dock:   RemLinkTMObject(tmobj->eo_LinkData);
  176.                      break;
  177.   }
  178.  
  179.  /* Remove links */
  180.  DeleteAllLinksTMObject((struct TMObject *) tmobj);
  181.  
  182.  /* Free resources */
  183.  if (tmobj->eo_CxObj) SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  184.  
  185.  /* Remove object from list */
  186.  Remove((struct Node *) tmobj);
  187.  
  188.  /* Free object */
  189.  FreeMem(tmobj,sizeof(struct TMObjectExec));
  190.  
  191.  /* All OK. */
  192.  return(TRUE);
  193. }
  194.  
  195. /* Change an Exec object */
  196. struct TMObject *ChangeTMObjectExec(struct TMHandle *handle,
  197.                                     struct TMObjectExec *tmobj,
  198.                                     struct TagItem *tags)
  199. {
  200.  struct TagItem *ti,*tstate;
  201.  
  202.  /* Scan tag list */
  203.  tstate=tags;
  204.  while (ti=NextTagItem(&tstate)) {
  205.  
  206.   DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  207.  
  208.   switch (ti->ti_Tag) {
  209.    case TMOP_Command:    {
  210.                           char *s=(char *) ti->ti_Data;
  211.                           if (s) tmobj->eo_Command=s;
  212.                          }
  213.                          break;
  214.    case TMOP_CurrentDir: {
  215.                           char *s=(char *) ti->ti_Data;
  216.                           if (s) tmobj->eo_CurrentDir=s;
  217.                          }
  218.                          break;
  219.    case TMOP_Delay:      tmobj->eo_Delay=ti->ti_Data;
  220.                          break;
  221.    case TMOP_ExecType:   {
  222.                           UWORD type=ti->ti_Data;
  223.  
  224.                           /* Sanity check */
  225.                           if ((type <= TMET_Network) || (type == TMET_Hook))
  226.                            tmobj->eo_Type=type;
  227.                          }
  228.                          break;
  229.    case TMOP_HotKey:     if (tmobj->eo_CxObj) {
  230.                           SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  231.                           tmobj->eo_CxObj=NULL;
  232.                          }
  233.  
  234.                          tmobj->eo_HotKey=(char *) ti->ti_Data;
  235.                          break;
  236.    case TMOP_Output:     {
  237.                           char *s=(char *) ti->ti_Data;
  238.                           if (s) tmobj->eo_Output=s;
  239.                          }
  240.                          break;
  241.    case TMOP_Path:       tmobj->eo_Path=(char *) ti->ti_Data;
  242.                          break;
  243.    case TMOP_Priority:   tmobj->eo_Priority=ti->ti_Data;
  244.                          break;
  245.    case TMOP_PubScreen:  tmobj->eo_PubScreen=(char *) ti->ti_Data;
  246.                          break;
  247.    case TMOP_Stack:      tmobj->eo_Stack=ti->ti_Data;
  248.                          break;
  249.   }
  250.  }
  251.  
  252.  /* HotKey set? Create Commodities object from HotKey description */
  253.  if  (tmobj->eo_HotKey && !tmobj->eo_CxObj &&
  254.       (tmobj->eo_CxObj=HotKey(tmobj->eo_HotKey,BrokerPort,
  255.                               (ULONG) &tmobj->eo_Link))) {
  256.  
  257.   DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->eo_CxObj);
  258.  
  259.   /* Attach object to broker */
  260.   AttachCxObj(Broker,tmobj->eo_CxObj);
  261.  
  262.   /* Commodities error? */
  263.   if (CxObjError(Broker)) {
  264.    SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  265.    tmobj->eo_CxObj=NULL;
  266.   }
  267.  }
  268.  
  269.  /* Set flags */
  270.  tmobj->eo_Flags=PackBoolTags(tmobj->eo_Flags,tags,flagmap);
  271.  
  272.  /* All OK */
  273.  return(TRUE);
  274. }
  275.  
  276. /* Allocate & Initialize a TMLink structure */
  277. struct TMLink *AllocLinkTMObjectExec(struct TMObjectExec *tmobj)
  278. {
  279.  struct TMLink *tml;
  280.  
  281.  /* Allocate memory for link structure */
  282.  if (tml=AllocMem(sizeof(struct TMLink),MEMF_CLEAR|MEMF_PUBLIC))
  283.   /* Initialize link structure */
  284.   tml->tml_Size=sizeof(struct TMLink);
  285.  
  286.  return(tml);
  287. }
  288.  
  289. /* Clear link to Dock object */
  290. void DeleteLinkTMObjectExec(struct TMLink *tml)
  291. {
  292.  struct TMObjectExec *tmobj=(struct TMObjectExec *) tml->tml_LinkedTo;
  293.  
  294.  tmobj->eo_LinkData=NULL;
  295. }
  296.  
  297. /* Copy a path list */
  298. BOOL CopyPathList(struct PathList **pla, struct PathList **plc,
  299.                   struct PathList *oldpl)
  300. {
  301.  struct PathList *pl1=oldpl,*pl2=*plc,*pl3=NULL;
  302.  
  303.  while (pl1) {
  304.   /* Get memory for path list entry */
  305.   if (!(pl3 || (pl3=AllocVec(sizeof(struct PathList),MEMF_PUBLIC|MEMF_CLEAR))))
  306.    return(FALSE); /* No more memory... */
  307.  
  308.   /* Copy path entry */
  309.   if (pl3->PathLock=DupLock(pl1->PathLock)) {
  310.    /* Copy successful, append new entry to list. Head of list? */
  311.    if (*pla)
  312.     pl2->NextPath=MKBADDR(pl3); /* No, append it to list */
  313.    else
  314.     *pla=pl3;                   /* Yes, set list anchor */
  315.  
  316.    /* Save pointer */
  317.    pl2=pl3;
  318.  
  319.    /* Invalidate pointer, next time a new PathList will be allocated */
  320.    pl3=NULL;
  321.   }
  322.  
  323.   /* Get next path list entry */
  324.   pl1=BADDR(pl1->NextPath);
  325.  }
  326.  
  327.  /* Free memory */
  328.  if (pl3) FreeVec(pl3);
  329.  
  330.  /* All OK */
  331.  *plc=pl2; /* Save pointer to new end of list */
  332.  return(TRUE);
  333. }
  334.  
  335. /* Free a path list */
  336. void FreePathList(struct PathList *pla)
  337. {
  338.  /* Check for NULL */
  339.  if (pla) {
  340.   struct PathList *pl1=pla,*pl2;
  341.  
  342.   /* Scan list */
  343.   do {
  344.    /* Get pointer to next entry */
  345.    pl2=BADDR(pl1->NextPath);
  346.  
  347.    /* Free entry */
  348.    UnLock(pl1->PathLock);
  349.    FreeVec(pl1);
  350.   } while (pl1=pl2);
  351.  }
  352. }
  353.  
  354. /* Build a path list from a string */
  355. static BOOL BuildPathList(struct PathList **pla, struct PathList **plc, char *s)
  356. {
  357.  struct FileInfoBlock *fib;
  358.  char *cp1,*cp2=s;
  359.  struct PathList *pl1=*plc,*pl2=NULL;
  360.  
  361.  /* Get memory for FIB */
  362.  if (!(fib=AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)))
  363.   return(FALSE);
  364.  
  365.  /* For every path part */
  366.  while (cp1=cp2) {
  367.   /* Search next path part */
  368.   if (cp2=strchr(cp1,',')) *cp2='\0'; /* Add string end character */
  369.  
  370.   /* Get memory for path list entry */
  371.   if (!(pl2 ||
  372.        (pl2=AllocVec(sizeof(struct PathList),MEMF_PUBLIC|MEMF_CLEAR)))) {
  373.    FreeVec(fib);
  374.    return(FALSE); /* No more memory */
  375.   }
  376.  
  377.   /* Get lock */
  378.   if (pl2->PathLock=Lock(cp1,SHARED_LOCK))
  379.    /* Is it a directory? */
  380.    if (Examine(pl2->PathLock,fib) && (fib->fib_DirEntryType>0)) {
  381.     /* Yes, it is a directory, append it to the list. Head of list? */
  382.     if (*pla)
  383.      pl1->NextPath=MKBADDR(pl2); /* No, append it to list */
  384.     else
  385.      *pla=pl2;                   /* Yes, set list anchor */
  386.  
  387.     /* Save pointer */
  388.     pl1=pl2;
  389.  
  390.     /* Invalidate pointer, next time a new PathList will be allocated */
  391.     pl2=NULL;
  392.    }
  393.    else UnLock(pl2->PathLock); /* No, it is a file */
  394.  
  395.   /* Restore string and move to next character */
  396.   if (cp2) *cp2++=',';
  397.  }
  398.  
  399.  *plc=pl1;              /* Save end of list */
  400.  if (pl2) FreeVec(pl2); /* Last Lock() failed, free memory */
  401.  FreeVec(fib);
  402.  
  403.  /* All OK. */
  404.  return(TRUE);
  405. }
  406.  
  407. #define NAMELEN    256  /* Buffer length for a file name */
  408. #define CMDLINELEN 4096 /* Buffer length for command line */
  409.  
  410. /* Build a CLI or ARexx command line (supports [] argument substitution) */
  411. static ULONG BuildCommandLine(char *buf, char *command, BPTR curdir,
  412.                               struct AppMessage *msg)
  413. {
  414.  ULONG cmdlen;      /* Command line length */
  415.  char *lp=command;  /* Pointer to current cmdline pos. */
  416.  char *contp=NULL;  /* Pointer AFTER [] place holder */
  417.  
  418.  /* Search for [] parameter place holder */
  419.  while (lp=strchr(lp,'['))
  420.   /* Place holder found? */
  421.   if (*(lp+1) == ']')
  422.    /* Yes, leave loop */
  423.    break;
  424.   else
  425.    /* No, skip to next one */
  426.    lp++;
  427.  
  428.  /* Copy command name to command line */
  429.  if (lp) {
  430.   /* [] parameter place holder found, copy first part of command */
  431.   cmdlen=lp-command;
  432.   strncpy(buf,command,cmdlen);
  433.   buf[cmdlen]='\0';
  434.   contp=lp+2;
  435.  }
  436.  else {
  437.   strcpy(buf,command); /* No [] parameter place holder */
  438.   cmdlen=strlen(buf);
  439.  }
  440.  lp=buf+cmdlen;
  441.  
  442.  /* Check for arguments */
  443.  if (msg) {
  444.   char *dir; /* Buffer for file names */
  445.  
  446.   /* Get memory for file names */
  447.   if (dir=AllocMem(NAMELEN,MEMF_PUBLIC)) {
  448.    struct WBArg *wa=msg->am_ArgList;  /* Pointer to WBArgs */
  449.    int i;                             /* Counter for WBArgs */
  450.  
  451.    for (i=msg->am_NumArgs; i; i--,wa++) {
  452.     char *name,*space;
  453.     ULONG namelen;
  454.  
  455.     /* Skip args which don't support locks! */
  456.     if (!wa->wa_Lock) continue;
  457.  
  458.     /* Append a space for each parameter */
  459.     if (cmdlen>CMDLINELEN-2) break;
  460.     *lp++=' ';
  461.     cmdlen++;
  462.  
  463.     /* Build parameter from Lock & name */
  464.     DEBUG_PRINTF("wa_Name: 0x%08lx\n",wa->wa_Name);
  465.     DEBUG_PRINTF("wa_Name: '%s'\n",wa->wa_Name);
  466.     if (*(wa->wa_Name)!='\0')
  467.      /* File name --> build complete path name */
  468.      if (SameLock(curdir,wa->wa_Lock)==LOCK_SAME)
  469.       /* File in current directory -> "<file>" */
  470.       name=(char *) wa->wa_Name;
  471.      else {
  472.       /* File in other directory -> "<path><seperator><file>" */
  473.       if (!NameFromLock(wa->wa_Lock,dir,NAMELEN)) continue;
  474.       if (!AddPart(dir,wa->wa_Name,NAMELEN)) continue;
  475.       name=dir;
  476.      }
  477.     else {
  478.      /* No file name --> Drawer */
  479.      if (!NameFromLock(wa->wa_Lock,dir,NAMELEN)) continue;
  480.      name=dir;
  481.     }
  482.     namelen=strlen(name);
  483.  
  484.     /* Handle special case: Space in a filename */
  485.     if (space=strchr(name,' ')) namelen+=2;
  486.  
  487.     /* Does parameter fit into commandline? */
  488.     if (cmdlen+namelen>CMDLINELEN-2) break;
  489.  
  490.     if (space) *lp++='"';   /* Quote file name (beginning) */
  491.     strcpy(lp,name);        /* Append parameter */
  492.     lp+=namelen;            /* Correct pointer */
  493.     if (space) {
  494.      lp--;                  /* Correct pointer */
  495.      *(lp-1)='"';           /* Quote file name (end) */
  496.     }
  497.     cmdlen+=namelen;        /* New command line length */
  498.  
  499.     DEBUG_PRINTF("Parameter: '%s'\n",buf);
  500.    }
  501.    FreeMem(dir,NAMELEN);
  502.   }
  503.  }
  504.  
  505.  /* Check for [] parameter place holder, Find closing bracket */
  506.  if (contp && (cmdlen+strlen(contp)<CMDLINELEN-1)) {
  507.   strcpy(lp,contp); /* Copy second part of command */
  508.   lp=lp+strlen(lp); /* Move to end of string */
  509.  }
  510.  else
  511.   *lp='\0';       /* Set string terminator */
  512.  
  513.  /* Return command line length */
  514.  return(lp-buf);
  515. }
  516.  
  517. /* Start CLI program */
  518. static BOOL StartCLIProgram(struct TMObjectExec *tmobj, struct AppMessage *msg)
  519. {
  520.  char *cmd;     /* Buffer for command line */
  521.  BOOL rc=FALSE;
  522.  
  523.  /* Get memory for command line */
  524.  if (cmd=AllocMem(CMDLINELEN,MEMF_PUBLIC)) {
  525.   BPTR newcd; /* Lock for program's current directory */
  526.  
  527.   if (newcd=Lock(tmobj->eo_CurrentDir,SHARED_LOCK)) {
  528.    BPTR ofh; /* AmigaDOS file handle (output) */
  529.  
  530.    /* Build command line */
  531.    BuildCommandLine(cmd,tmobj->eo_Command,newcd,msg);
  532.  
  533.    /* Open output file */
  534.    if (ofh=Open(tmobj->eo_Output,MODE_NEWFILE)) {
  535.     BPTR ifh; /* AmigaDOS file handle (input) */
  536.     struct MsgPort *newct=NULL;          /* New ConsoleTask pointer */
  537.  
  538.     /* Is the output file an interactive file? */
  539.     if (IsInteractive(ofh)) {
  540.      struct MsgPort *oldct;  /* Old ConsoleTask pointer */
  541.  
  542.      /* Yes. We need the same file as input file for CTRL-C/D/E/F redirection */
  543.      /* Set our ConsoleTask to the new output file, so that we can re-open it */
  544.      newct=((struct FileHandle *) BADDR(ofh))->fh_Type;
  545.      oldct=SetConsoleTask(newct);
  546.  
  547.      /* Open the new input file (Now ifh points to the same file as ofh) */
  548.      ifh=Open("CONSOLE:",MODE_OLDFILE);
  549.  
  550.      /* Change back to old ConsoleTask */
  551.      SetConsoleTask(oldct);
  552.     }
  553.     /* Non-interactive output, open dummy input file */
  554.     else ifh=Open(DefaultOutput,MODE_OLDFILE);
  555.  
  556.     if (ifh) {
  557.      struct PathList *pla=NULL,*plc=NULL;
  558.  
  559.      /* Build path list, local path first, then global path*/
  560.      if (BuildPathList(&pla,&plc,tmobj->eo_Path) &&
  561.          CopyPathList(&pla,&plc,GlobalPath)) {
  562.       BPTR oldcd; /* pointer to old current directory */
  563.  
  564.       /* Go to program's current directory */
  565.       oldcd=CurrentDir(newcd);
  566.  
  567.       /* Start program */
  568.       if (SystemTags(cmd,SYS_Output,     ofh,
  569.                          SYS_Input,      ifh,
  570.                          SYS_Asynch,     TRUE, /* Run program asynchron */
  571.                          SYS_UserShell,  TRUE, /* Use user specified shell */
  572.                          NP_StackSize,   tmobj->eo_Stack,
  573.                          NP_Priority,    tmobj->eo_Priority,
  574.                          NP_Path,        MKBADDR(pla),
  575.                          NP_ConsoleTask, newct,
  576.                          TAG_DONE)!=-1)
  577.        rc=TRUE; /* Program started! */
  578.  
  579.       /* Go back to old current directory */
  580.       CurrentDir(oldcd);
  581.      }
  582.      if (!rc) FreePathList(pla); /* Free path list if program wasn't started */
  583.      if (!rc) Close(ifh); /* Close input file if program wasn't started */
  584.     }
  585.     if (!rc) Close(ofh); /* Close output file if program wasn't started */
  586.    }
  587.    UnLock(newcd);
  588.   }
  589.   FreeMem(cmd,CMDLINELEN);
  590.  }
  591.  return(rc);
  592. }
  593.  
  594. /* Start WB program */
  595. static BOOL StartWBProgram(struct TMObjectExec *tmobj, struct AppMessage *msg)
  596. {
  597.  struct MsgPort *hp;     /* Port of WBStart-Handler */
  598.  struct WBStartMsg wbsm; /* Message for WBStart-Handler */
  599.  BOOL rc=FALSE;
  600.  
  601.  /* Build message for WBStart-Handler */
  602.  wbsm.wbsm_Msg.mn_Node.ln_Pri= 0;
  603.  wbsm.wbsm_Msg.mn_ReplyPort  = DummyPort;
  604.  wbsm.wbsm_Name              = tmobj->eo_Command;
  605.  wbsm.wbsm_DirLock           = Lock(tmobj->eo_CurrentDir,SHARED_LOCK);
  606.  wbsm.wbsm_Stack             = tmobj->eo_Stack;
  607.  wbsm.wbsm_Prio              = tmobj->eo_Priority;
  608.  wbsm.wbsm_NumArgs           = msg ? msg->am_NumArgs : 0;
  609.  wbsm.wbsm_ArgList           = msg ? msg->am_ArgList : 0;
  610.  
  611.  /* Try to send a message to the WBStart-Handler */
  612.  Forbid();
  613.  hp=FindPort(WBS_PORTNAME);
  614.  if (hp) PutMsg(hp,(struct Message *) &wbsm);
  615.  Permit();
  616.  
  617.  /* No WBStart-Handler, try to start it! */
  618.  if (!hp) {
  619.   BPTR ifh;
  620.  
  621.   if (ifh=Open(DefaultOutput,MODE_NEWFILE)) {
  622.    BPTR ofh;
  623.  
  624.    if (ofh=Open(DefaultOutput,MODE_OLDFILE))
  625.     /* Start handler */
  626.     if (SystemTags(WBS_LOADNAME,SYS_Input,ifh,
  627.                                 SYS_Output,ofh,
  628.                                 SYS_Asynch,TRUE,
  629.                                 SYS_UserShell,TRUE,
  630.                                 NP_ConsoleTask,NULL,
  631.                                 NP_WindowPtr,NULL,
  632.                                 TAG_DONE) != -1) {
  633.      int i;
  634.  
  635.      /* Handler started, try to send message (Retry up to 5 seconds) */
  636.      for (i=0; i<10; i++) {
  637.       /* Try to send message */
  638.       Forbid();
  639.       hp=FindPort(WBS_PORTNAME);
  640.       if (hp) PutMsg(hp,(struct Message *) &wbsm);
  641.       Permit();
  642.  
  643.       /* Message sent? Yes, leave loop */
  644.       if (hp) break;
  645.  
  646.       /* No, wait 1/2 second */
  647.       Delay(25);
  648.      }
  649.     }
  650.     /* Handler not started, close file handles */
  651.     else {
  652.      Close(ofh);
  653.      Close(ifh);
  654.     }
  655.    else Close(ifh);
  656.   }
  657.  }
  658.  
  659.  /* Could we send the message? */
  660.  if (hp) {
  661.   /* Get reply message */
  662.   WaitPort(DummyPort);
  663.   GetMsg(DummyPort);
  664.   rc=wbsm.wbsm_Stack; /* Has tool been started? */
  665.   DEBUG_PRINTF("Return Code %ld\n",rc);
  666.  }
  667.  
  668.  /* Free lock */
  669.  if (wbsm.wbsm_DirLock) UnLock(wbsm.wbsm_DirLock);
  670.  
  671.  return(rc);
  672. }
  673.  
  674. /* Start ARexx program */
  675. static BOOL StartARexxProgram(struct TMObjectExec *tmobj,
  676.                               struct AppMessage *msg)
  677. {
  678.  char *cmd;     /* Buffer for command line */
  679.  BOOL rc=FALSE;
  680.  
  681.  /* Get memory for command line */
  682.  if (cmd=AllocMem(CMDLINELEN,MEMF_PUBLIC)) {
  683.   BPTR newcd; /* Lock for program's current directory */
  684.  
  685.   if (newcd=Lock(tmobj->eo_CurrentDir,SHARED_LOCK)) {
  686.    ULONG cmdlen; /* Command line length */
  687.    BPTR oldcd;   /* Lock for old current directory */
  688.  
  689.    /* Build command line */
  690.    cmdlen=BuildCommandLine(cmd,tmobj->eo_Command,newcd,msg);
  691.  
  692.    /* Go to program's current directory */
  693.    oldcd=CurrentDir(newcd);
  694.  
  695.    /* Send ARexx command */
  696.    rc=SendARexxCommand(cmd,cmdlen);
  697.  
  698.    /* Go back to old current directory */
  699.    CurrentDir(oldcd);
  700.    UnLock(newcd);
  701.   }
  702.   FreeMem(cmd,CMDLINELEN);
  703.  }
  704.  return(rc);
  705. }
  706.  
  707. /* Start Network program */
  708. static BOOL StartNetworkProgram(struct TMObjectExec *tmobj)
  709. {
  710.  BOOL rc=FALSE;
  711.  
  712.  /* Network installed? */
  713.  if (LocalEntity) {
  714.   char *cmd=tmobj->eo_Command;
  715.   char *hostname;
  716.  
  717.   /* Search '@' seperator */
  718.   if (hostname=strchr(cmd,'@')) {
  719.    /* Host name found */
  720.    ULONG cmdlen=hostname-cmd+1;
  721.    struct Entity *RemoteEntity;
  722.  
  723.    /* Increment pointer */
  724.    hostname++;
  725.  
  726.    DEBUG_PRINTF("Host name: '%s'\n",hostname);
  727.  
  728.    /* Find entity "ToolManager" on remote machine */
  729.    if (RemoteEntity=FindEntity(hostname,ToolManagerName,LocalEntity,NULL)) {
  730.     struct Transaction *trans;
  731.  
  732.     DEBUG_PRINTF("Remote entity: 0x%08lx\n",RemoteEntity);
  733.  
  734.     /* Allocate transaction */
  735.     if (trans=AllocTransaction(TRN_AllocReqBuffer, cmdlen,
  736.                                TAG_DONE)) {
  737.      char *buffer=trans->trans_RequestData;
  738.  
  739.      DEBUG_PRINTF("Transaction: 0x%08lx\n",trans);
  740.  
  741.      /* Init transaction */
  742.      strncpy(buffer,cmd,cmdlen-1);
  743.      buffer[cmdlen-1]='\0';
  744.      trans->trans_ReqDataActual=cmdlen;
  745.      trans->trans_Timeout=10; /* 10 secs timeout for remote machine */
  746.  
  747.      DEBUG_PRINTF("Remote command: '%s'\n",buffer);
  748.  
  749.      /* Do transaction */
  750.      DoTransaction(RemoteEntity,LocalEntity,trans);
  751.      rc=(trans->trans_Error == ENVOYERR_NOERROR);
  752.  
  753.      DEBUG_PRINTF("Network error: %ld\n",trans->trans_Error);
  754.  
  755.      /* Free transaction */
  756.      FreeTransaction(trans);
  757.     }
  758.  
  759.     /* Release remote entity */
  760.     LoseEntity(RemoteEntity);
  761.    }
  762.   }
  763.  }
  764.  return(rc);
  765. }
  766.  
  767. /* Input desctription structure for ParseIX() */
  768. static struct InputXpression ParseBuffer={IX_VERSION};
  769.  
  770. void kprintf(char *, ...);
  771.  
  772. /* Create an input event from a Commodities description string */
  773. static struct InputEvent *CreateInputEvent(struct TMObjectExec *tmobj)
  774. {
  775.  struct InputEvent *ie;
  776.  
  777.  /* Allocate memory for input event */
  778.  if (ie=AllocMem(sizeof(struct InputEvent),MEMF_CLEAR|MEMF_PUBLIC)) {
  779.  
  780.   /* Parse description string */
  781.   if (!ParseIX(tmobj->eo_Command,&ParseBuffer)) {
  782.  
  783.    /* Description OK, initialize input event */
  784.    ie->ie_Class    =ParseBuffer.ix_Class;
  785.    ie->ie_Code     =ParseBuffer.ix_Code;
  786.    ie->ie_Qualifier=ParseBuffer.ix_Qualifier;
  787.  
  788.    /* All OK */
  789.    return(ie);
  790.   }
  791.  
  792.   /* Error in description string, free input event */
  793.   FreeMem(ie,sizeof(struct InputEvent));
  794.  }
  795.  return(NULL);
  796. }
  797.  
  798. /* Start program */
  799. static void StartProgram(struct TMObjectExec *tmobj, struct AppMessage *msg)
  800. {
  801.  struct AppMessage *args=(tmobj->eo_Flags & EO_Arguments) ? msg : NULL;
  802.  BOOL rc=FALSE;
  803.  
  804.  /* Check for command */
  805.  if (!tmobj->eo_Command) return; /* Nothing to do */
  806.  
  807.  /* Check for ToFront flag */
  808.  if (tmobj->eo_Flags & EO_ToFront) {
  809.   /* Move screen to front */
  810.   struct Screen *s=LockPubScreen(tmobj->eo_PubScreen);
  811.  
  812.   if (s) {
  813.    ScreenToFront(s);
  814.    UnlockPubScreen(NULL,s);
  815.   }
  816.  }
  817.  
  818.  /* Check for program type */
  819.  switch (tmobj->eo_Type) {
  820.   case TMET_CLI:     rc=StartCLIProgram(tmobj,args);
  821.                      break;
  822.   case TMET_WB:      rc=StartWBProgram(tmobj,args);
  823.                      break;
  824.   case TMET_ARexx:   rc=StartARexxProgram(tmobj,args);
  825.                      break;
  826.   case TMET_Dock:    /* Dock already linked or can we create a link? */
  827.                      if (tmobj->eo_LinkData ||
  828.                          (tmobj->eo_LinkData=AddLinkTMObject(tmobj->eo_Handle,
  829.                                                              tmobj->eo_Command,
  830.                                                              TMOBJTYPE_DOCK,
  831.                                                  (struct TMObject *) tmobj))) {
  832.                       /* Yes, activate it */
  833.                       CallActivateTMObject(tmobj->eo_LinkData,NULL);
  834.                       rc=TRUE;
  835.                      }
  836.                      break;
  837.   case TMET_HotKey:  /* Input event already created or can we create it? */
  838.                      if (tmobj->eo_LinkData ||
  839.                          (tmobj->eo_LinkData=CreateInputEvent(tmobj))) {
  840.                       /* Yes */
  841.                       struct InputEvent *ie=tmobj->eo_LinkData;
  842.  
  843.                       /* Set time stamp */
  844.                       CurrentTime(&ie->ie_TimeStamp.tv_secs,
  845.                                   &ie->ie_TimeStamp.tv_micro);
  846.  
  847.                       /* Enqueue event */
  848.                       AddIEvents(tmobj->eo_LinkData);
  849.                       rc=TRUE;
  850.                      }
  851.                      break;
  852.   case TMET_Network: rc=StartNetworkProgram(tmobj); /* No args possible */
  853.                      break;
  854.   case TMET_Hook:    {
  855.                       struct Hook *hook=(struct Hook *) tmobj->eo_Command;
  856.                       HookFuncPtr Entry = (HookFuncPtr) hook->h_Entry;
  857.  
  858.                       /* Call hook function. Calling conventions:          */
  859.                       /* A0 (hook)   : pointer to hook structure           */
  860.                       /* A1 (message): pointer to AppMessage (may be NULL) */
  861.                       /* A2 (object) : value of hook->h_Data               */
  862.                       /* Return Code : BOOL, FALSE for failure             */
  863.                       rc=Entry(hook,args,hook->h_Data);
  864.                      }
  865.                      break;
  866.  }
  867.  
  868.  /* Error? */
  869.  if (!rc) DisplayBeep(NULL);
  870. }
  871.  
  872. /* Send timer request */
  873. static void SendTimerRequest(struct TMObjectExec *tmobj)
  874. {
  875.  struct timerequest *tr=(struct timerequest *) &tmobj->eo_TimerReq;
  876.  
  877.  /* Initialize timer request */
  878.  tr->tr_node.io_Command=TR_ADDREQUEST;
  879.  tr->tr_time.tv_secs=labs(tmobj->eo_Delay);
  880.  tr->tr_time.tv_micro=0;
  881.  
  882.  /* Send timer request */
  883.  SendIO((struct IORequest *) tr);
  884.  tmobj->eo_Link.tml_Active=(void *) TRUE;
  885. }
  886.  
  887. /* Activate an Exec object */
  888. void ActivateTMObjectExec(struct TMLink *tml, struct AppMessage *msg)
  889. {
  890.  struct TMObjectExec *tmobj=(struct TMObjectExec *) tml->tml_Linked;
  891.  
  892.  DEBUG_PRINTF("Activate/Exec (0x%08lx)\n",msg);
  893.  
  894.  /* Is timer active? */
  895.  if (tmobj->eo_Link.tml_Active) {
  896.   /* Yes. a) got timer event, b) user wants to stop last request */
  897.   struct IORequest *tr=(struct IORequest *) &tmobj->eo_TimerReq;
  898.  
  899.   /* Check timer request */
  900.   if (CheckIO(tr)) {
  901.    /* a) Timer event finished, remove it. */
  902.    WaitIO(tr);
  903.    tmobj->eo_Link.tml_Active=FALSE;
  904.  
  905.    /* Start program, no arguments */
  906.    StartProgram(tmobj,NULL);
  907.  
  908.    /* repeat event? */
  909.    if (tmobj->eo_Delay<0) SendTimerRequest(tmobj);
  910.   }
  911.   else {
  912.    /* b) user wants to stop last request, abort it */
  913.    AbortIO(tr);
  914.    WaitIO(tr);
  915.    tmobj->eo_Link.tml_Active=FALSE;
  916.   }
  917.  }
  918.  /* Timer not active, start program or time request */
  919.  else if (tmobj->eo_Delay!=0) SendTimerRequest(tmobj);
  920.  
  921.  /* Start program */
  922.  else StartProgram(tmobj,msg);
  923. }
  924.